<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta content="width=device-width, initial-scale=1" name="viewport">
    <title>SceneModel with batched, double-precision geometries, annotations, rendered with logarithmic depth
        buffer
        enabled</title>
        <link href="../css/pageStyle.css" rel="stylesheet"/>

    <style>

        #myNavCubeCanvas {
            position: absolute;
            width: 250px;
            height: 250px;
            bottom: 50px;
            right: 10px;
            z-index: 200000;
        }

        .xeokit-camera-pivot-marker {
            color: #ffffff;
            position: absolute;
            width: 25px;
            height: 25px;
            border-radius: 15px;
            border: 2px solid #ebebeb;
            background: black;
            visibility: hidden;
            box-shadow: 5px 5px 15px 1px #000000;
            z-index: 10000;
            pointer-events: none;
        }

        .annotation-marker {
            color: #ffffff;
            line-height: 1.8;
            text-align: center;
            font-family: "monospace";
            font-weight: bold;
            position: absolute;
            width: 25px;
            height: 25px;
            border-radius: 15px;
            border: 2px solid #ffffff;
            background: black;
            visibility: hidden;
            box-shadow: 5px 5px 15px 1px #000000;
            z-index: 0;
        }

        .annotation-label {
            pointer-events: none;
            position: absolute;
            max-width: 250px;
            min-height: 50px;
            padding: 8px;
            padding-left: 12px;
            padding-right: 12px;
            background: #ffffff;
            color: #000000;
            -webkit-border-radius: 3px;
            -moz-border-radius: 3px;
            border-radius: 8px;
            border: #ffffff solid 2px;
            box-shadow: 5px 5px 15px 1px #000000;
            z-index: 90000;
        }

        .annotation-label:after {
            content: '';
            position: absolute;
            border-style: solid;
            border-width: 8px 12px 8px 0;
            border-color: transparent white;
            display: block;
            width: 0;
            z-index: 1;
            margin-top: -11px;
            left: -12px;
            top: 20px;
        }

        .annotation-label:before {
            content: '';
            position: absolute;
            border-style: solid;
            border-width: 9px 13px 9px 0;
            border-color: transparent #ffffff;
            display: block;
            width: 0;
            z-index: 0;
            margin-top: -12px;
            left: -15px;
            top: 20px;
        }

        .annotation-title {
            font: normal 20px arial, serif;
            margin-bottom: 8px;
        }

        .annotation-desc {
            font: normal 14px arial, serif;
        }

    </style>

</head>
<body>

<canvas id="myCanvas"></canvas>

<canvas id="myNavCubeCanvas"></canvas>

<div id="info" style="visibility:visible">
    <h1>SceneModel with batched, double-precision geometries, annotations, rendered with logarithmic depth buffer
        enabled</h1>
    <br>
    <ul>
        <li>
            <a href="../../docs/class/src/viewer/Viewer.js~Viewer.html"
               target="_other">Viewer</a>
        </li>
        <li>
            <a href="../../docs/class/src/plugins/AnnotationsPlugin/AnnotationsPlugin.js~AnnotationsPlugin.html"
               target="_other">AnnotationsPlugin</a>
        </li>
        <li>
            <a href="../../docs/class/src/viewer/scene/model/SceneModel.js~SceneModel.html"
               target="_other">SceneModel</a>
        </li>
    </ul>
</div>

</body>

<script type="module">

    //------------------------------------------------------------------------------------------------------------------
    // Import the modules we need for this example
    //------------------------------------------------------------------------------------------------------------------

    import {Viewer, NavCubePlugin, math, SceneModel, AnnotationsPlugin} from "../../dist/xeokit-sdk.min.es.js";

    //------------------------------------------------------------------------------------------------------------------
    // Create a Viewer with a logarithmic depth buffer
    //------------------------------------------------------------------------------------------------------------------

    const viewer = new Viewer({
        canvasId: "myCanvas",
        transparent: true,
        logarithmicDepthBufferEnabled: true // <<--- Enable logarithmic depth buffer
    });

    //------------------------------------------------------------------------------------------------------------------
    // Configure Camera
    //
    // Since our viewer has a logarithmic depth buffer, 
    // we can set a huge distance for the Camera's far clipping plane
    //------------------------------------------------------------------------------------------------------------------

    viewer.camera.eye = [1841341.4943041557, 2435.7015793568917, -5182009.256037191];
    viewer.camera.look = [1842215.561857325, -98.53293939639616, -5177009.767748618];
    viewer.camera.up = [0.07693555158566205, 0.8946686100264034, 0.4400556773132614];

    viewer.camera.perspective.near = 1.0;
    viewer.camera.perspective.far = 100000000; // 1000000km

    viewer.camera.ortho.near = 1.0;
    viewer.camera.ortho.far = 100000000; // 1000000km

    //------------------------------------------------------------------------------------------------------------------
    // Configure CameraControl
    //
    // Show a dot at the pivot point, whenever we orbit the Camera
    //------------------------------------------------------------------------------------------------------------------

    viewer.cameraControl.followPointer = true;

    const pivotElement = document.createRange().createContextualFragment("<div class='xeokit-camera-pivot-marker'></div>").firstChild;
    document.body.appendChild(pivotElement);
    viewer.cameraControl.pivotElement = pivotElement;

    //------------------------------------------------------------------------------------------------------------------
    // Tweak edges color
    //------------------------------------------------------------------------------------------------------------------

    viewer.scene.edgeMaterial.edgeColor = [.3, .3, .3];

    //----------------------------------------------------------------------------------------------------------------------
    // Add a NavCube
    //----------------------------------------------------------------------------------------------------------------------

    new NavCubePlugin(viewer, {
        canvasId: "myNavCubeCanvas",
        visible: true,           // Initially visible (default)
        size: 250,               // NavCube size in pixels (default is 200)
        alignment: "topRight",   // Align NavCube to top-left of Viewer canvas
        topMargin: 170,          // 170 pixels margin from top of Viewer canvas
        cameraFly: true,       // Fly camera to each selected axis/diagonal
        cameraFitFOV: 45,        // How much field-of-view the scene takes once camera has fitted it to view
        cameraFlyDuration: 0.5 // How long (in seconds) camera takes to fly to each new axis/diagonal
    });

    //------------------------------------------------------------------------------------------------------------------
    // Mouse over Entities to highlight them
    //------------------------------------------------------------------------------------------------------------------

    let lastPickedEntity = null;
    viewer.scene.input.on("mousemove", function (coords) {
        const hit = viewer.scene.pick({
            canvasPos: coords
        });
        if (hit) {
            if (!lastPickedEntity || hit.entity.id !== lastPickedEntity.id) {
                if (lastPickedEntity) {
                    lastPickedEntity.highlighted = false;
                }
                lastPickedEntity = hit.entity;
                hit.entity.highlighted = true;
            }
        } else {
            if (lastPickedEntity) {
                lastPickedEntity.highlighted = false;
                lastPickedEntity = null;
            }
        }
    });

    //------------------------------------------------------------------------------------------------------------------
    // Create an AnnotationsPlugin, with which we'll programmatically create some annotations
    //------------------------------------------------------------------------------------------------------------------

    const annotations = new AnnotationsPlugin(viewer, {

        markerHTML: "<div class='annotation-marker' style='background-color: {{markerBGColor}};'>{{glyph}}</div>",
        labelHTML: "<div class='annotation-label' style='background-color: {{labelBGColor}};'><div class='annotation-title'>{{title}}</div><div class='annotation-desc'>{{description}}</div></div>",

        values: {
            markerBGColor: "red",
            glyph: "X",
            title: "Untitled",
            description: "No description"
        },
        surfaceOffset: 0.1
    });

    annotations.on("markerClicked", (annotation) => {
        annotation.labelShown = !annotation.labelShown;
    });

    annotations.createAnnotation({
        id: "myAnnotation1",
        worldPos: [-5067.961471839821, -250.0000044173721, -5374.59914398724],
        occludable: true,       // Optional, default is true
        markerShown: true,      // Optional, default is true
        labelShown: true,       // Optional, default is true
        values: {               // HTML template values
            glyph: "A1",
            title: "My annotation 1",
            description: "My description 1"
        }
    });

    annotations.createAnnotation({
        id: "myAnnotation2",
        worldPos: [2370.2301617494086, -250.00002714159513, -2411.109239155929],
        occludable: true,
        markerShown: true,
        labelShown: true,
        values: {
            glyph: "A2",
            title: "My annotation 2",
            description: "My description 2"
        }
    });

    annotations.createAnnotation({
        id: "myAnnotation3",
        worldPos: [-4928.770029692367, -248.04742621837806, 203.85962935103305],
        occludable: true,
        markerShown: true,
        labelShown: true,
        values: {
            glyph: "A3",
            title: "My annotation 3",
            description: "My description 3"
        }
    });

    annotations.createAnnotation({
        id: "myAnnotation4",
        worldPos: [-2091.8285643799104, -722.4263479019601, -3000.0077140932412],
        occludable: true,
        markerShown: true,
        labelShown: true,
        values: {
            glyph: "A4",
            title: "My annotation 4",
            description: "My description 4"
        }
    });
    //
    //
    // var i = 10;
    //
    // viewer.scene.input.on("mouseclicked", (coords) => {
    //
    //     var pickResult = viewer.scene.pick({
    //         canvasPos: coords,
    //         pickSurface: true  // <<------ This causes picking to find the intersection point on the entity
    //     });
    //
    //     if (pickResult) {
    //
    //         const annotation = annotations.createAnnotation({
    //             id: "myAnnotation" + i,
    //             pickResult: pickResult, // <<------- initializes worldPos and entity from PickResult
    //             occludable: true,       // Optional, default is true
    //             markerShown: true,      // Optional, default is true
    //             labelShown: true,       // Optional, default is true
    //             values: {               // HTML template values
    //                 glyph: "A" + i,
    //                 title: "My annotation " + i,
    //                 description: "My description " + i
    //             },
    //         });
    //
    //         console.log(pickResult.worldPos);
    //         i++;
    //     }
    // });

    //----------------------------------------------------------------------------------------------------------------------
    // Programmatically build a SceneModel
    // containing a bunch of table-shaped models,
    // without using geometry
    //----------------------------------------------------------------------------------------------------------------------

    const vboSceneModel = new SceneModel(viewer.scene, {
        id: "table",
        isModel: true,
        position: [0, 0, 0],
        scale: [1, 1, 1],
        rotation: [0, 0, 0],
        edges: true
    });

    const OFFSET = 5000.0;
    const SIZE = 100;

    for (let x = -OFFSET; x < OFFSET; x += 2500.0) {
        for (let z = -OFFSET; z < OFFSET; z += 2500.0) {
            const origin = [x, 0, z];
            buildTable(vboSceneModel, origin, SIZE);
        }
    }

    vboSceneModel.finalize();

    viewer.cameraFlight.jumpTo(viewer.scene);

    //------------------------------------------------------------------------------------------------------------------
    // Creates a simple table-shaped model with the given SceneModel,
    // without reusing geometry, and centered at the given origin
    //------------------------------------------------------------------------------------------------------------------

    function buildTable(vboSceneModel, origin, size = 1) {

        let meshId = math.createUUID();

        vboSceneModel.createMesh({
            id: meshId,
            origin: origin, // This mesh's positions and transforms are relative to the origin
            primitive: "triangles",
            positions: [
                1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1,
                1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1,
                -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1
            ],
            normals: [
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0,
                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,
                0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15,
                16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23
            ],
            position: [-4 * size, -6 * size, -4 * size],
            scale: [size, 3 * size, size],
            rotation: [0, 0, 0],
            color: [1, 0.3, 0.3]
        });

        vboSceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        vboSceneModel.createMesh({
            id: meshId,
            origin: origin,
            primitive: "triangles",
            positions: [
                1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1,
                1, 1, 1, 1, 1, -1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1,
                -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1
            ],
            normals: [
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
                -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15,
                16, 17, 18, 16, 18, 19, 20, 21, 22, 20, 22, 23
            ],
            position: [4 * size, -6 * size, -4 * size],
            scale: [size, 3 * size, size],
            rotation: [0, 0, 0],
            color: [0.3, 1.0, 0.3]
        });

        vboSceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        vboSceneModel.createMesh({
            id: meshId,
            origin: origin,
            positions: [
                1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1,
                -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1,
                -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1
            ],
            normals: [
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
                -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0,
                -1, 0, 0, -1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19,
                20, 21, 22, 20, 22, 23
            ],
            position: [4 * size, -6 * size, 4 * size],
            scale: [size, 3 * size, size],
            rotation: [0, 0, 0],
            color: [0.3, 0.3, 1.0]
        });

        vboSceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        vboSceneModel.createMesh({
            id: meshId,
            origin: origin,
            positions: [
                1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1,
                -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1,
                -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1
            ],
            normals: [
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
                -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19,
                20, 21, 22, 20, 22, 23
            ],
            position: [-4 * size, -6 * size, 4 * size],
            scale: [size, 3 * size, size],
            rotation: [0, 0, 0],
            color: [1.0, 1.0, 0.0]
        });

        vboSceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });

        meshId = math.createUUID();

        vboSceneModel.createMesh({
            id: meshId,
            origin: origin,
            positions: [
                1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1,
                -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1,
                -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, -1
            ],
            normals: [
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0,
                -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1
            ],
            indices: [
                0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7, 8, 9, 10, 8, 10, 11, 12, 13, 14, 12, 14, 15, 16, 17, 18, 16, 18, 19,
                20, 21, 22, 20, 22, 23
            ],
            position: [0, -3 * size, 0],
            scale: [6 * size, 0.5 * size, 6 * size],
            rotation: [0, 0, 0],
            color: [1.0, 0.3, 1.0]
        });

        vboSceneModel.createEntity({
            meshIds: [meshId],
            isObject: true
        });
    }

</script>
</html>
